package com.seaside.park.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.seaside.common.bean.Result;
import com.seaside.park.bean.Fee;
import com.seaside.park.mapper.FeeMapper;
import com.seaside.park.service.NotifyService;
import com.seaside.park.service.ParkService;
import com.seaside.park.service.ParkingService;
import com.seaside.park.service.RemoteService;
import com.seaside.parkCommon.bean.*;
import com.seaside.parkCommon.mapper.*;
import com.seaside.parkCommon.util.HttpUtil;
import com.seaside.parkCommon.vo.OrderPlatesVO;
import com.seaside.parkCommon.vo.yz.OrderMessage;
import com.seaside.parkCommon.vo.yz.PunitoryParkVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@Slf4j
public class RemoteStatusAPI {

    @Autowired
    private ParkPlaceMapper parkPlaceMapper;

    @Autowired
    private WhiteListMapper whiteListMapper;

    @Autowired
    private AlarmMapper alarmMapper;

    @Autowired
    private ParkRecordMapper parkRecordMapper;

    @Autowired
    private ReserveOrderMapper reserveOrderMapper;

    @Autowired
    private TodayChangeChargeMapper changeChargeMapper;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private RemoteService remoteService;

    @Autowired
    private FeeMapper feeMapper;

    @Autowired
    private ParkZoneMapper parkZoneMapper;

    @Autowired
    private ParkService parkService;

    @Autowired
    private ParkingService parkingService;

    public static final ConcurrentHashMap<String, String> distribution = new ConcurrentHashMap();

    /**
     * 查询一个空车位
     * @param zoneId
     * @return
     */
    @RequestMapping("/api/status/getOneParkPlaceBlack")
    public Result<ParkPlace> getOneParkPlaceBlack(@RequestParam int zoneId) {
        List<ParkPlace> parkPlaceBlanks = parkPlaceMapper.getParkPlaceBlank(zoneId);
        if (parkPlaceBlanks != null && parkPlaceBlanks.size() > 0) {
            return Result.OK("查询空车位信息成功！", parkPlaceBlanks.get(0));
        } else {
            return Result.Error("未查询到空车位！");
        }
    }

    /**
     * 根据车场ID获取所有车位情况
     *
     * @param zoneId
     * @return
     */
    @RequestMapping("/api/status/getParkPlaceInfo")
    public Result<List<ParkPlace>> getParkPlaceInfo(int zoneId) {
        QueryWrapper<ParkPlace> wrapper = new QueryWrapper<>();
        wrapper.eq("zone_id", zoneId).eq("valid",1);
        List<ParkPlace> ret = parkPlaceMapper.selectList(wrapper);
        if (ret.size() > 0) {
            return Result.OK("查询车位信息成功!", ret);
        } else {
            return Result.Error("查询失败!");
        }
    }

    @RequestMapping("/api/status/getParkPlaceTo")
    public Result<ParkPlace> getParkPlaceTo(int zoneId) {
        synchronized (this) {
            if (!ParkingService.generated) {
                parkingService.getParkPlaceForOrder();
            }
        }
        Queue<String> orderQuery = ParkingService.AllOrderParkPlace.get(zoneId);
        return Result.OK("分配成功!",parkService.OrderParkPlace(orderQuery,zoneId,0));
    }

    /**
     * 清除分配记录
     *
     */
    public static void cleanDistribution(String carPlate){
        distribution.remove(carPlate);
    }

    /**
     * 指引大屏所需的数据接口
     *
     * @param plate:传入识别的车牌号
     */

    @RequestMapping("/api/status/chargeIfOrderPlate")
    @ResponseBody
    public Result<String> chargeIfOrderPlate(@RequestParam String plate, @RequestParam int zoneId) {
        //查看是否白名单
        QueryWrapper<WhiteList> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("car_plate", plate).eq("zone_id", zoneId);
        //白名单车辆不显示
        if (whiteListMapper.selectCount(queryWrapper) > 0) {
            return Result.Error("没有找到订单!");
        }

        if(zoneId == 14){
            if(null != RemoteStatusAPI.distribution.get(plate)){
                return Result.OK(RemoteStatusAPI.distribution.get(plate));
            }else{
                return Result.Error("没有找到订单!");
            }
        }

        //商业区自主分位，形成订单各种操作
        if (zoneId == 9) {
            try {
                if (distribution.get(plate) != null) {
                    return Result.OK("该车为预定车辆", distribution.get(plate).toString());
                } else {
                    //查找空位
                    List<ParkPlace> parkPlaceList = parkPlaceMapper.getParkPlaceBlank(zoneId);
                    //转换ID为云智的编码
                    ParkZone parkZone = parkZoneMapper.selectById(zoneId);
                    /**
                     * 发送云智预约短信
                     */
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH点mm分");
                    LocalDateTime nowDateTime = LocalDateTime.now();

                    OrderMessage message = new OrderMessage();
                    String carPlate = plate;

                    message.setCarPlate(carPlate);
                    String[] messageVariable = new String[4];
                    messageVariable[0] = carPlate;
                    messageVariable[1] = parkZone.getZoneName();
                    messageVariable[2] = nowDateTime.format(formatter);
                    message.setMessageVariable(messageVariable);

                    if (parkPlaceList.size() > 0) {
                        //人工智能分析落位,目前先人工分配
                        ParkPlace parkPlace = parkPlaceList.get(0);
                        distribution.put(carPlate, parkPlace.getParkNo());
                        //生成订单
                        ReserveOrder order = new ReserveOrder();
                        order.setCarPlate(plate);
                        order.setBerthNumber(parkPlace.getParkNo());
                        order.setOrderTime(new Date());
                        order.setOrderInTime(new Date());
                        order.setParkPlaceId(parkPlace.getParkId());
                        //四大道测试ID
                        order.setParkZoneId(parkZone.getZoneNo());
                        reserveOrderMapper.insert(order);
                        //修改泊位预约列表
                        String tempList = parkPlace.getTempList();
                        if (StringUtils.isBlank(tempList)) {
                            parkPlace.setTempList(order.getCarPlate());
                        } else {
                            tempList += ("|" + order.getCarPlate());
                            parkPlace.setTempList(tempList);
                        }
                        parkPlace.setIfOrder(1);
                        parkPlace.setLastChangeTime(new Date());
                        parkPlaceMapper.updateById(parkPlace);

                        //远程打开预约灯光
                        remoteService.changeLampStatus(parkZone.getZoneNo(), order.getBerthNumber(), "ON");

                        if (parkPlace == null) {
                            log.warn("未找到车位信息：【" + JSON.toJSONString(order) + "】");
                            return Result.Error("未找到车位信息！");
                        }

                        //发送云智短信
                        messageVariable[3] = parkPlace.getParkNo();

                        String jsonString = "[" + JSON.toJSONString(message, SerializerFeature.WriteMapNullValue) + "]";
                        if (HttpUtil.jsonPost("https://rain.yzparking.cn/notice/barui/receiveCallData", jsonString)) {
                            log.info("预约车位发送短信成功!");
                        } else {
                            log.error("预约车位发送短信失败!");
                        }
                        return Result.OK("该车为预定车辆", parkPlace.getParkNo());
                    } else {
                        distribution.put(carPlate, "临停车位");
                        messageVariable[3] = "临停车位";
                        String jsonString = "[" + JSON.toJSONString(message, SerializerFeature.WriteMapNullValue) + "]";
                        if (HttpUtil.jsonPost("https://rain.yzparking.cn/notice/barui/receiveCallData", jsonString)) {
                            log.info("预约车位发送短信成功!");
                        } else {
                            log.error("预约车位发送短信失败!");
                        }
                        return Result.OK("该车为预定车辆", "临停车位");
                    }
                }

            } catch (Exception e) {
                log.error("分配车位发送错误!" + e.getMessage());
                return Result.Error("没有找到订单!");
            }
        } else {
            List<OrderPlatesVO> orderPlatesVOs = reserveOrderMapper.getTodayOrderByPlate(plate);
            if (orderPlatesVOs.size() > 0) {
                return Result.OK("该车为预定车辆", orderPlatesVOs.get(0).getBerthNumber());
            } else {
                return Result.Error("没有找到订单!");
            }
        }
    }


    /**
     * 根据车位号码进行车位信息沟通
     *
     * @param parkPlace
     * @return
     */
    @RequestMapping("/api/status/updateParkPlaceInfo")
    public Result statusInfo(ParkPlace parkPlace) {
        QueryWrapper<ParkPlace> wrapper = new QueryWrapper<>();
        wrapper.eq("park_no", parkPlace.getParkNo()).eq("zone_id", parkPlace.getZoneId());
        parkPlace.setLastChangeTime(new Date());
        parkPlace.setSmallImageData(parkPlace.getSmallImageData());
        if (parkPlaceMapper.update(parkPlace, wrapper) > 0) {
            return Result.OK("更新成功!");
        } else {
            return Result.Error("更新失败!");
        }
    }

    @RequestMapping("/api/status/resetParkPlace")
    public Result resetParkPlace(int zoneId) {
        if (parkPlaceMapper.resetParkPlaceStatus(zoneId) > 0) {
            return Result.OK("重启重置成功!");
        } else {
            return Result.Error("重启重置失败!");
        }
    }

    /**
     * 查询车位的预定列表
     *
     * @param parkPlace
     * @return
     */
    @RequestMapping("/api/status/getParkPlaceTempList")
    public Result getParkPlaceTempList(ParkPlace parkPlace) {
        QueryWrapper<ParkPlace> wrapper = new QueryWrapper<>();
        wrapper.eq("park_no", parkPlace.getParkNo()).eq("zone_id", parkPlace.getZoneId());
        ParkPlace parkPlaceRet = parkPlaceMapper.selectOne(wrapper);
        if (parkPlaceRet != null) {
            return Result.OK("查询成功!", parkPlaceRet.getTempList());
        } else {
            return Result.Error("查询失败!");
        }
    }

    /**
     * 查询哪一层空闲
     *
     * @param
     * @return
     */
    @RequestMapping("/api/status/queryFloor")
    public Result<String> queryFloor(int zoneId) {
        return Result.OK("查询成功!","2");
    }

    /**
     * 上传异常信息
     *
     * @param alarm
     * @return
     */
    @RequestMapping("/api/status/postAlarm")
    public Result postAlarm(Alarm alarm) {
        alarm.setTime(new Date());
        if (alarmMapper.insert(alarm) > 0) {
            return Result.OK("更新成功!");
        } else {
            return Result.Error("更新失败!");
        }
    }

    /**
     * 接收停车记录
     *
     * @param parkNo
     * @param zoneId
     * @param carPlate
     * @param event
     * @return
     */
    @RequestMapping("/api/status/postParkRecord")
    public Result postParkRecord(String parkNo, int zoneId, String carPlate, String event) {
        ParkRecord parkRecord;
        if (event.equalsIgnoreCase("IN")) {
            parkRecord = new ParkRecord();
            parkRecord.setParkNo(parkNo);
            parkRecord.setCarPlate(carPlate);
            parkRecord.setZoneId(zoneId);
            parkRecord.setInTime(new Date());
            if (parkRecordMapper.insert(parkRecord) > 0) {
                return Result.OK("更新成功!");
            } else {
                return Result.Error("更新失败!");
            }
        } else {
            //发送云智离位信息
            //编号转化成序号，和云智统一
            QueryWrapper<ParkZone> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("zone_id", zoneId);
            ParkZone parkZone = parkZoneMapper.selectOne(queryWrapper);

            notifyService.NotifyYZ(parkNo,parkZone.getZoneNo(),carPlate, "OUT");
            //查询入场记录，更新离开时间字段
            QueryWrapper<ParkRecord> wrapper = new QueryWrapper<>();
            wrapper.eq("car_plate", carPlate).eq("park_no", parkNo).eq("zone_id", zoneId).isNull("out_time");
            wrapper.orderByDesc("in_time");
            List<ParkRecord> parkRecords = parkRecordMapper.selectList(wrapper);
            if (parkRecords == null || parkRecords.isEmpty()){
                return Result.OK("未查询到入场记录");
            }
            parkRecord = parkRecords.get(0);
            parkRecord.setOutTime(new Date());
            if (parkRecordMapper.updateById(parkRecord) > 0) {
                return Result.OK("更新成功!");
            } else {
                return Result.Error("更新失败!");
            }

        }
    }

    /**
     * 查询改变计费规则记录
     *
     * @param parkZoneNo
     * @return
     */
    @RequestMapping("/api/status/getChangeCharge")
    public Result getChangeCharge(String parkZoneNo) {
        QueryWrapper<TodayChangeCharge> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("zone_no", parkZoneNo).eq("if_deal", "否");
        List<TodayChangeCharge> changeChargeList = changeChargeMapper.selectList(queryWrapper);

        if (changeChargeList != null) {
            return Result.OK("查询成功!", changeChargeList);
        } else {
            return Result.Error("查询失败!");
        }
    }

    /**
     * 停车场计费规则获取
     *
     * @param parkZoneNo
     * @return
     */
    @RequestMapping("/api/status/getRuleFee")
    public Result<Fee> getFeeRule(String parkZoneNo) {
        Fee fee = feeMapper.selectById(parkZoneNo);
        if (fee != null) {
            return Result.OK("查询成功!", fee);
        } else {
            return Result.OK("查询成功!", "");
        }
    }

    /**
     * 根据车位号码，获取该车位昨日停车数据
     *
     * @param parkZoneNo
     * @return
     */
    @RequestMapping("/api/status/getTodayParkRecord")
    public Result<ParkRecord> getTodayParkRecord(String parkNo, int parkZoneNo) {
        return Result.OK("查询成功!", parkRecordMapper.getYestdayParkRecordByParkNo(parkNo, parkZoneNo));
    }

    @RequestMapping("/api/status/getMonthParkRecord")
    public Result<ParkRecord> getMonthParkRecord(String parkNo, int parkZoneNo, String year, String month, int pageNum, int pageSize) {
        return Result.OK("查询成功!", parkRecordMapper.getMonthParkRecordByParkNo(parkNo, parkZoneNo, year + "-" + month + "-01", (pageNum - 1) * pageSize, pageSize));
    }

    @RequestMapping("/api/status/getMonthTotalParkRecord")
    public Result<Long> getMonthTotalParkRecord(String parkNo, int parkZoneNo, String year, String month) {
        return Result.OK("查询成功!", parkRecordMapper.getMonthTotalMinute(parkNo, parkZoneNo, year + "-" + month + "-01"));
    }

    /**
     * 惩罚性收费接口
     *
     * @param changeChargeId
     * @param type
     * @return
     */
    @RequestMapping("/api/status/confirmChangeCharge")
    public Result confirmChangeCharge(String parkZoneNo, String changeChargeId, String type) {
        try {
            TodayChangeCharge changeCharge = changeChargeMapper.selectById(changeChargeId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            PunitoryParkVO punitoryParkVO = new PunitoryParkVO();
            punitoryParkVO.setParkId(parkZoneNo);
            punitoryParkVO.setCarPlate(changeCharge.getCarPlate());
            punitoryParkVO.setDateTime(sdf.format(new Date()));
            punitoryParkVO.setPunitoryGrade(type);
            punitoryParkVO.setBerthNumber("");
            punitoryParkVO.setPunitoryReason(changeCharge.getChangeInfo());
            notifyService.postPunitoryParkNotify(punitoryParkVO);
            changeCharge.setIfSend(1);
            changeCharge.setIfDeal("是");
            changeChargeMapper.updateById(changeCharge);
            return Result.OK("收费规则处理完成!");
        } catch (Exception e) {
            log.error(e.getMessage());
            return Result.Error("收费规则处理失败！");
        }
    }
}
